package CBBOT::Clanbase;

use strict;
use warnings;
use lib '/home/services/cbbot/2.0/';
use Scalar::Util qw(looks_like_number);
use CBBOT::Config;
use LWP::Simple;
use HTML::TagParser;
use URI::Fetch;

my $dbh	= CBBOT::Config::get_dbh();

sub clan_rank {
	my($input, $channel, $type) = @_;
	my $setup = $dbh->selectrow_hashref("
		SELECT clanid, ladderid FROM setup WHERE channel=?", undef, $channel);

	my $cid = undef;
	if(!looks_like_number($input)) {
		my($trigger, $what) = split(/\s/, $input);
		if(looks_like_number($what)) {
			$cid = $what;
		} else {
			$cid = $setup->{clanid};
		}
	} else {
		$cid = $input;
	}

	if(defined($setup)) {
		my $html = get("http://clanbase.ggl.com/claninfo.php?wars=1&cid=$cid&lid=$setup->{ladderid}");
		if($html =~ /Rank:\s<b>(\d+)<\/b>\s\((.*?)\spoints\)/) {
			my($rank, $points) = ($1, $2);
			if($type eq 'withtext') {
				return "$points points ($rank. place)\n";
			} elsif($type eq 'plain') {
				$points =~ s/,//;
				return $points;
			} else {
				return "Unknow return type ($type)\n";
			}
		} else {
			return "Couldn't fetch ranking (clan might be unranked)\n";
		}
	} else {
		return "Channel \"$channel\" isn't registered\n";
	}
}

sub last_match {
	my($input, $channel, $type) = @_;
	my $setup = $dbh->selectrow_hashref("
		SELECT clanid, ladderid, shortname FROM setup WHERE channel=?", undef, $channel);

	my $cid = undef;
	if(!looks_like_number($input)) {
		my($trigger, $what) = split(/\s/, $input);
		if(looks_like_number($what)) {
			$cid = $what;
		} else {
			$cid = $setup->{clanid};
		}
	} else {
		$cid = $input;
	}

	if(defined($setup)) {
		my $tags = HTML::TagParser->new("http://clanbase.ggl.com/claninfo.php?wars=1&cid=$cid&lid=$setup->{ladderid}");
		my @valuecells = $tags->getElementsByClassName("valuecell2");
		my $date = $valuecells[1]->innerText;
		my $opponent = $valuecells[2]->innerText;
		my $maps = $valuecells[3]->innerText;
		my $them = $valuecells[4]->innerText;
		my $points = $valuecells[5]->innerText;
		my ($result, $us) = (0, 0);

		if($them > 24) {
			my @loss = $tags->getElementsByClassName("valuecellloss");
			$us = $loss[0]->innerText;
		} else { 
			my @win = $tags->getElementsByClassName("valuecellwin");
			$us = $win[0]->innerText;
		}

		($result, $points) = split(/\s/, $points);
		
		if($type eq 'withtext') {
			my $total;
			if($result !~ /waiting/) { 
				$points .= 'p';
				$total = "$result$points";
			} else {
				$points = "";
				$total = $result;
			}
			return "[$date] $setup->{shortname} vs $opponent $us-$them ($total) on $maps\n";
		} elsif($type eq 'plain') {
			return $result;		
		} else {
			return "Unknow return type ($type)\n";
		}
	} else {
		return "Channel \"$channel\" isn't registered\n";
	}
}

sub map_results {
	my($cid, $channel) = @_;
	my $ref = $dbh->selectrow_hashref("SELECT clanid, ladderid FROM setup WHERE channel=?", undef, $channel);
	my $clan = HTML::TagParser->new("http://clanbase.ggl.com/claninfo.php?wars=1&cid=$cid&lid=$ref->{ladderid}");
	my @list = $clan->getElementsByClassName("valuecell");
	push(@list, $clan->getElementsByClassName("valuecell2"));
	my(@maps, @res);

	foreach my $item (@list) {
		if($item->innerText =~ /\w+\s\/\s\w+/) {
			my($m1, $m2) = split(/\//, $item->innerText);
			push(@maps, $m1);
			push(@maps, $m2);
		}
		if($item->innerText =~ /(((-|\+)\s\d+|waiting\.\.\.|none))/) {
			if($item->innerText =~ /none/) {
				push(@res, "+ 1");
				push(@res, "+ 1");
			} else {
				push(@res, $item->innerText);
				push(@res, $item->innerText);
			}
		}
	}

	my %mapres;
	my $i = 0;
	foreach my $map (@maps) {
		$map =~ s/\s//;
		if($res[$i] =~ /\+/) {
			$mapres{$map}{"wins"}++;
		} else {
			$mapres{$map}{"loss"}++;
		}
		$i++;
	}

	my %finalres; 
	for my $key (keys %mapres) {
		if(!defined($mapres{$key}{"loss"})) { $mapres{$key}{"loss"} = 0; } 
		if(!defined($mapres{$key}{"wins"})) { $mapres{$key}{"wins"} = 0; } 	
		$finalres{$key} = ($mapres{$key}{"wins"} / (1 + $mapres{$key}{"loss"}));
	}

	return %finalres;
}

sub get_opponents {
	my($cid, $channel) = @_;
	my $ref = $dbh->selectrow_hashref("SELECT clanid, ladderid, shortname FROM setup WHERE channel=?", undef, $channel);
	my $clan = HTML::TagParser->new("http://clanbase.ggl.com/claninfo.php?wars=1&cid=$cid&lid=$ref->{ladderid}");
	my @list = $clan->getElementsByClassName("valuecell");
	push(@list, $clan->getElementsByClassName("valuecell2"));
	my(@opponents, @results);
	my $i = 0;

	foreach my $cell (@list) {
		if($cell->innerText =~ /\d{2}:\d{2}/) {
			$i = 1;
			next;
		}
		if($i == 1) {
			if($cell->innerText =~ /$ref->{shortname}/) {
				my $ourclan = $ref->{shortname} . int(rand(1000));
				push(@opponents, $ourclan);
				$i = 0;
			} else {
				push(@opponents, $cell->innerText);
				$i = 0;
			}
		}
		if($cell->innerText =~ /(((-|\+)\s\d+|waiting\.\.\.|none))/) {
			push(@results, $cell->innerText);
		}
	}		

	my %opsandres;
	@opsandres{@opponents} = @results;
	return %opsandres;
}

sub judge_clan {
	my $start_ts = time;
	my($input, $channel) = @_;
	my($trigger, $cid) = split(/\s/, $input);

	if(looks_like_number($cid) && $channel =~ /^#/) {
		my $setup = $dbh->selectrow_hashref("
			SELECT clanid, ladderid, shortname FROM setup WHERE channel=?", undef, $channel);

		my $rank = clan_rank($cid, $channel, 'plain');
		if(looks_like_number($rank)) {

			# Compare ranks 
			my $ourrank = clan_rank($setup->{clanid}, $channel, 'plain');
			my $rankdiff;
			if($rank > $ourrank) {
				$rankdiff = "+";
				$rankdiff .= $rank - $ourrank;
			} elsif($ourrank > $rank) {
				$rankdiff = "-";
				$rankdiff .= $ourrank - $rank;
			} else {
				$rankdiff = 'Same rank!'; 
			}
			$rank .= 'p';
			
			# Grab clan name and check for suspended members
			my($clanname, $suspendedmembers) = ("", "");
			my $clanpagehtml = get("http://clanbase.ggl.com/claninfo.php?cid=$cid");
			if($clanpagehtml =~ /<title>(.*)<\/title>/) {
				$clanname = $1;
				$clanname =~ s/ClanBase\s-\s//;
				} 
			if($clanpagehtml =~ /Suspended\smembers/) {
				$suspendedmembers = "Clan has one or more suspended members";
			} else {
				$suspendedmembers = "No suspended members";
			}

			# Favourite map		
			my $wartags = HTML::TagParser->new("http://clanbase.ggl.com/claninfo.php?wars=1&cid=$cid&lid=$setup->{ladderid}");
			my @valuecells = $wartags->getElementsByClassName("valuecell2");
			my @theiropponents = $wartags->getElementsByClassName("slink");
			push(@valuecells, $wartags->getElementsByClassName("valuecell"));

			my @mostplayed;
			foreach my $map (@valuecells) {
				next if $map->innerText !~ /\w+\s\/\s\w+/;
				my($m1,$m2) = split(/\//, $map->innerText);
				$m1 =~ s/\s//;
				$m2 =~ s/\s//;
				push(@mostplayed, $m1);		
				push(@mostplayed, $m2);
			}

			# Find map with most occurrences
			my %c;
			my @max = ("", 0);
			map { $c{$_}++; @max = ($_, $c{$_}) if $c{$_} > $max[1]; } @mostplayed;
			my $maptotal = scalar(@mostplayed);
			my $map = "$max[0] ($max[1] out of $maptotal maps)";

			# Upvotes and downvotes 
			my $votepagetags = HTML::TagParser->new("http://clanbase.ggl.com/claninfo.php?cid=$cid&judge=1");
			my @votes = $votepagetags->getElementsByTagName("small");
			my $votecount;
			foreach my $vote (@votes) {
				$votecount .= $vote->innerText;
				$votecount .= "-";
			}

			my($d2, $d1, $gg, $u1, $u2) = 0;
			($d2, $d1, $gg, $u1, $u2) = split(/-/, $votecount);
			my $downvotes = $d2 + $d1 . " down";
			my $upvotes = $u2 + $u1 . " up";

			# Number of conflicts 
			my $clanjudgepage = get("http://clanbase.ggl.com/claninfo.php?cid=$cid&judge=1");
			my $conflicts;
			if($clanjudgepage =~ /involved\sin\s<b>(\d+)<\/b>\smatchconflicts/) {
				$conflicts = $1;
			}
			my $selfstarted;
			if($clanjudgepage =~ /started\s<b>(\d+)<\/b>\sthemselves/) {
				$selfstarted= $1;
			}

			# Check for recently added members 
			my $logpagetags = HTML::TagParser->new("http://clanbase.ggl.com/claninfo.php?cid=$cid&log=1");
			my @dates = $logpagetags->getElementsByClassName("valuecell");
			my @log = $logpagetags->getElementsByClassName("valuecell2");
			my $last;
			if(defined($dates[0])) {
				$last = $dates[0]->innerText;
			}
			my $action = $log[2]->innerText; 
			my $newmember = undef;
			$last =~ s/(\w+\s\d+)(\d{2}:\d{2})/$1 @ $2/;
		
			if($action =~ /Added\smember/) {
				$newmember = "Last member was added on $last";
			}

			# Check to see if we have played the same opponent 
			my %theiropponents = get_opponents($cid, $channel);
			my %ouropponents   = get_opponents($setup->{clanid}, $channel);   
			my($sameopponent, $playedusbefore) = (undef, undef);
		
			my %cmp = map { $_ => 1 } keys %theiropponents;
			my $soi = 0;
		
			for my $key (keys %ouropponents) {
				if(exists($cmp{$key} )) {
					$theiropponents{$key} =~ s/\s//;
					$ouropponents{$key} =~ s/\s//;
					$sameopponent .= "$key ($theiropponents{$key}/$ouropponents{$key}) ";			
					$sameopponent =~ s/&nbsp;//;
					++$soi;
				} 
			}

			# Our victories and defeats against them
			my($wonoverus, $beatenthem) = (undef, undef);	
			my($losses, $beats) = (1,1);
			for my $key2 (keys %theiropponents) {
				if($key2 =~ /$setup->{shortname}/) {
					if($theiropponents{$key2} =~ /\+/) {
						$wonoverus = "They've beaten us $losses time(s)";
						++$losses;
					} else {
						$beatenthem = "We've beaten them $beats time(s)";
						++$beats;
					}
				}
			}

			# Map suggestion
			my %theirmapres = map_results($cid, $channel);
			my %ourmapres 	= map_results($setup->{clanid}, $channel);
			my @map_suggestion = (-1000, "");
	
			for my $mapsug (keys %ourmapres) {
				if(exists($theirmapres{$mapsug})) {
					if(($ourmapres{$mapsug} - $theirmapres{$mapsug}) > $map_suggestion[0]) { 
						$map_suggestion[0] = sprintf("%.2f", $ourmapres{$mapsug} - $theirmapres{$mapsug});
						$map_suggestion[1] = $mapsug; 
					}
				}
			}

			# Average ranking between opponents
			my $warshtml = get("http://clanbase.ggl.com/claninfo.php?wars=1&cid=$cid&lid=$setup->{ladderid}");
			my @cids = $warshtml =~ /cid=(\d+)/g;
			my $avgranko = 0;
			my @ranks;
			my $enough = 0;

			foreach my $ccid (@cids) {
				next if $ccid eq $setup->{clanid} || $ccid eq $cid; 
				last if $enough == 20;
				my $rank = clan_rank($ccid, $channel, 'plain');
				$rank =~ s/,//;
				if($rank =~ /\d+/) {
					push(@ranks, $rank);
				}
				$enough++;
			}

			my $nops = scalar(@ranks);

			foreach my $rrank (@ranks) {
				$avgranko = $avgranko + $rrank;
			}	
			$avgranko = int($avgranko / $nops);
		
			my $avgrankodiff;
			if($ourrank > $avgranko) {
				$avgrankodiff = '-';
				$avgrankodiff .= $ourrank - $avgranko;
			} elsif($avgranko > $ourrank) {
				$avgrankodiff = '+';
				$avgrankodiff .= $avgranko - $ourrank;
			}
			$avgranko .= 'p';
		
			# Return everything back
			my @return = "Judging [$clanname]";
			push(@return, "Rank: $rank ($rankdiff)");
			push(@return, "Avgrank opponents: $avgranko ($avgrankodiff)");
			push(@return, "Map: $map");
			push(@return, "Suggested map: $map_suggestion[1] ($map_suggestion[0])");
			
			if(defined($wonoverus) || defined($beatenthem)) {
				push(@return, $wonoverus);
				push(@return, $beatenthem);
			} else {
				push(@return, "Never played against them.");
			}

			push(@return, "Votes: $upvotes / $downvotes");
			push(@return, "Conflicts: $conflicts($selfstarted)") if defined $conflicts;
			push(@return, $newmember) if defined($newmember);
	
			if(defined($sameopponent)) {
				push(@return, "Same opponents ($soi): $sameopponent");
			} else {
				push(@return, "Never played the same opponent");
			}
	
			push(@return, $suspendedmembers);
			my $runtime = time - $start_ts;
			push(@return, "Time: $runtime seconds");
	
			return @return;
		} else {
			return $rank; 
		}
	} else {
		return "Unknow clan id or broken channel\n";
	}
}

1;

